package com.pilipili.serverapi.manageUser.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pilipili.common.Exception.BusinessRuntimeException;
import com.pilipili.common.service.AbstractService;
import com.pilipili.common.util.BeanUtils;
import com.pilipili.common.util.TokenUtils;
import com.pilipili.serverapi.ErrorCode;
import com.pilipili.serverapi.manageUser.dto.req.ManageUserInfoDto;
import com.pilipili.serverapi.manageUser.dto.req.ManageUserLoginDto;
import com.pilipili.serverapi.manageUser.dto.req.ManageUserSighUpDto;
import com.pilipili.serverapi.manageUser.dto.resp.ManageLoginResultDto;
import com.pilipili.serverapi.manageUser.entity.ManageUser;
import com.pilipili.serverapi.manageUser.entity.Permission;
import com.pilipili.serverapi.manageUser.entity.Role;
import com.pilipili.serverapi.manageUser.repository.ManageUserRepository;
import com.pilipili.serverapi.manageUser.repository.RoleRepository;
import com.pilipili.serverapi.manageUser.repository.TokenRepository;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * 用户管理Service
 *
 * @author chen.guosheng
 */
@Service
public class ManageUserService extends AbstractService<ManageUserRepository, ManageUser, Long> {

    private static final Logger LOG = LoggerFactory.getLogger(ManageUserService.class);

    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private TokenRepository tokenRepository;

//    private ManageLoginResultDto genAndSaveToken(ManageUser manageUser) {
//        String tokenSrc = manageUser.getUserName() + System.currentTimeMillis();
//        String token = TokenUtils.generateToken(tokenSrc);
//        tokenRepository.saveManageUser(token, manageUser.getId());
//        return new ManageLoginResultDto(manageUser.getId(), manageUser.getUserName(), token);
//    }


    //添加用户，默认角色为普通用户
    @Transactional
    public ManageLoginResultDto addManageUser(ManageUserSighUpDto manageUserSighUpDto){
        if (!manageUserSighUpDto.getPassword().equals(manageUserSighUpDto.getVerifyPassword())){
            throw new BusinessRuntimeException(ErrorCode.PASSWORD_INCONSISTENT);
        }
        if(this.repository.findByUserName(manageUserSighUpDto.getUserName()) != null){
            throw new BusinessRuntimeException(ErrorCode.EXSIST_USER);
        }
        ManageUser manageUser = new ManageUser(manageUserSighUpDto.getUserName(), manageUserSighUpDto.getPassword(),
                manageUserSighUpDto.getMobile(), manageUserSighUpDto.getEmail());
        manageUser.setRoles(new HashSet<Role>());
        manageUser.getRoles().add(roleRepository.getOne(3L));
        this.repository.save(manageUser);
//        return genAndSaveToken(manageUser);
        return login(new ManageUserLoginDto(manageUserSighUpDto.getUserName(), manageUserSighUpDto.getPassword()));
    }

    @Transactional
    public ManageLoginResultDto login(ManageUserLoginDto manageUserLoginDto){
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(manageUserLoginDto.getUserName(), manageUserLoginDto.getPassword());
            //登录不在该处处理，交由shiro处理
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            if (subject.isAuthenticated()) {
                return new ManageLoginResultDto(this.repository.findByUserName(manageUserLoginDto.getUserName()).getId(), manageUserLoginDto.getUserName(), subject.getSession().getId().toString());
            }else{
                throw new BusinessRuntimeException(ErrorCode.SHIRO_ERROR);
            }
        }catch (IncorrectCredentialsException | UnknownAccountException e){
            throw new BusinessRuntimeException(ErrorCode.USER_NOT_FOUND);
        }
    }

    @Transactional
    public void editInfo(ManageUserInfoDto manageUserInfoDto){
        Optional<ManageUser> manageUser = this.repository.findById(manageUserInfoDto.getId());
        if(manageUser.isPresent()){
            BeanUtils.copyProperties(manageUserInfoDto, manageUser.get());
            this.repository.save(manageUser.get());
        }
    }


    @Transactional
    public Set<Role> findRolesByUserId(Long id){
        Optional<ManageUser> manageUser = this.repository.findById(id);
        if(manageUser.isPresent()){
            ManageUser manageUser1 = manageUser.get();
            if(manageUser1.getRoles() != null){
                return manageUser1.getRoles();
            }
            return new HashSet<Role>();
        }
        else{
            return new HashSet<Role>();
        }
    }

    @Transactional
    public Set<Permission> findPermissionsByUserId(Long id){
        Set<Role> roles = findRolesByUserId(id);
        Set<Permission> permissions = new HashSet<Permission>();
        if(!roles.isEmpty()){
            for(Role role : roles){
                Optional<Role> role1 = roleRepository.findById(role.getId());
                if(role1.isPresent()){
                    permissions.addAll(role1.get().getPermissions());
                }
            }
        }
        return permissions;
    }

    @Transactional
    public ManageUser findUserByUserName(String userName){
        ManageUser manageUser = this.repository.findByUserName(userName);
        return manageUser;
    }
}
